//10 - 22/01
//Una de las canciones se queda fija

//09 - 18/01
//Pasamos a 11 luces

//08 - 08/01
//Usamos digital 7 como cambio de escena
//Se cambia la dirección de las luces

//07 - 10/10
//Ajustes de presets para la demo

//06 - 03/10
//Añadimos un botón extra de control que permite cambiar de kit
//Hacemos mezcla de modo demo y modo concierto

//05 - 26/09
//Utilizaremos el botón más cercano a la fuente para contolar el juego de colores (kit)
//Se crea una máquina de estdos
//Todas las luces cambian al mismo color dentro de un kit

//05 - 26/09
//Utilizaremos el botón más cercano a la fuente para contolar el juego de colores (kit)
//Se crea una máquina de estdos
//Todas las luces cambian al mismo color dentro de un kit

//04 - 19/09
//Seis botones
//Ojo, que la version 3 no funciona, que la he sobreescrito con la cuatro

//03 - 18/09
//Cuatro botones, por las entradas analógicas

//02 - 17/09
//Se implementa el código de MACE. Es vital NO CAMBIAR los pines de los #defines
//Dos ejemplos d código

//01 - 16/09
//Un único shiftbrite que cambia de color cada segundo

#define changemodepin 8
#define digitalchangemodepin 7

#define latchpin 9 
#define enablepin 10
#define datapin 11
#define clockpin 13

#define totalLeds 11
#define totalKits 6

int iCanales[totalLeds][3] = {0};
boolean bBotones[totalLeds] = {false};

int iInternalState = 0;
boolean bPressChangeMode = false;
int iCurrentKit = 0;


int iKitColores[totalKits][totalLeds][3] = {{{979,70,0},{919,26,0},{1004,122,0},{920,57,0},{986,105,0},{965,93,0},{907,153,0},{675,28,0},{1013,138,0},{962,64,0},{1002,0,0}},
{{0,1006,406},{846,304,511},{994,988,0},{0,817,511},{1023,394,0},{1023,192,18},{246,273,511},{973,161,428},{979,975,359},{482,1023,0},{0,0,444}},
{{0,0,107},{931,0,37},{988,95,236},{933,0,0},{1023,76,0},{0,0,223},{0,102,358},{933,0,0},{855,68,0},{366,0,265},{0,0,314}},
{{0,374,0},{0,524,85},{0,247,0},{188,258,87},{0,648,0},{0,524,165},{1023,1023,464},{37,1023,92},{654,639,369},{0,760,0},{0,797,0}},
{{990,389,218},{68,236,10},{111,205,37},{76,629,10},{43,314,46},{43,844,41},{128,277,23},{86,699,18},{86,405,18},{84,216,18},{25,291,0}},
{{0,858,0},{0,859,0},{0,859,0},{0,859,0},{863,0,0},{863,0,0},{863,0,0},{863,0,0},{863,0,0},{862,0,0},{862,0,0}}};


void setup() {

  pinMode(datapin, OUTPUT);
  pinMode(latchpin, OUTPUT);
  pinMode(enablepin, OUTPUT);
  pinMode(clockpin, OUTPUT);

  pinMode(digitalchangemodepin, INPUT);
  for (int f=2; f<=7; f++) {
    pinMode(f, INPUT);
  }

  SPCR = (1<<SPE)|(1<<MSTR)|(0<<SPR1)|(0<<SPR0);

  digitalWrite(latchpin, LOW);
  digitalWrite(enablepin, LOW);

  Serial.begin(9600);

}


void loop() {

  //bPressChangeMode = (digitalRead(changemodepin))==HIGH;
  bPressChangeMode = (digitalRead(digitalchangemodepin))==HIGH;

  switch(iInternalState) {
  case 0:
    if (bPressChangeMode) {
      Serial.println("CHANGE [PRESS]");
      iInternalState = 1;
      iCurrentKit++;
      if (iCurrentKit >= totalKits) iCurrentKit = 0; 
      for (int f=0; f<=iCurrentKit; f++){
        iCanales[f][0] = iCanales[f][1] = iCanales[f][2] = 128;                       
      }
      for (int f=iCurrentKit+1; f<totalLeds; f++){
        iCanales[f][0] = iCanales[f][1] = iCanales[f][2] = 0;                       
      }       
    } 
    else {
      teclado(iCurrentKit);       
    }
    break;
  case 1:
    if (!bPressChangeMode) {
      Serial.println("CHANGE [RELEASE]");      
      iInternalState = 0;
      for (int f=0; f<totalLeds; f++){
        iCanales[f][0] = iCanales[f][1] = iCanales[f][2] = 0;             
      }
    }    
    break;
  }

  SB_WriteLEDData();
}


void teclado(int iKit){

  if (iKit==5) {
    float fMult = (1.0 + sin (millis()/(425.0*PI))) / 2.0;
    for (int f=0; f<6; f++) {
      iCanales[totalLeds-1-f][0] =  iKitColores[iKit][f][0]*fMult;
      iCanales[totalLeds-1-f][1] =  iKitColores[iKit][f][1]*fMult;
      iCanales[totalLeds-1-f][2] =  iKitColores[iKit][f][2]*fMult;        
      bBotones[f] = true;      
    }
    for (int f=6; f<totalLeds; f++) {
      iCanales[totalLeds-1-f][0] =  iKitColores[iKit][f][0]*fMult;
      iCanales[totalLeds-1-f][1] =  iKitColores[iKit][f][1]*fMult;
      iCanales[totalLeds-1-f][2] =  iKitColores[iKit][f][2]*fMult;        
      bBotones[f] = true;      
    } 
    return;
  }

  for (int f=0; f<6; f++) {
    if (analogRead(f) < 512 && bBotones[f]) {
      iCanales[totalLeds-1-f][0] = iCanales[totalLeds-1-f][1] = iCanales[totalLeds-1-f][2] = 0;      
      bBotones[f] = false;
    } 
    else if (analogRead(f) >= 512 && !bBotones[f]){
      //Serial.print("A");
      //Serial.println(f);
      iCanales[totalLeds-1-f][0] =  iKitColores[iKit][f][0];
      iCanales[totalLeds-1-f][1] =  iKitColores[iKit][f][1];
      iCanales[totalLeds-1-f][2] =  iKitColores[iKit][f][2];        
      bBotones[f] = true;      
    }
  }
  for (int f=6; f<totalLeds; f++) {
    if ((digitalRead(f-4))==LOW && bBotones[f]) {
      iCanales[totalLeds-1-f][0] = iCanales[totalLeds-1-f][1] = iCanales[totalLeds-1-f][2] = 0;      
      bBotones[f] = false;
    } 
    else if ((digitalRead(f-4))==HIGH && !bBotones[f]){
      Serial.print("Press ");      
      Serial.println(f);      
      iCanales[totalLeds-1-f][0] =  iKitColores[iKit][f][0];
      iCanales[totalLeds-1-f][1] =  iKitColores[iKit][f][1];
      iCanales[totalLeds-1-f][2] =  iKitColores[iKit][f][2];        
      bBotones[f] = true;      
    }
  }
}




void SB_SendPacket(int SB_CommandMode, int r, int g, int b) {

  if (SB_CommandMode == B01) r =  g = b = 127;

  SPDR = SB_CommandMode << 6 | b>>4;
  while(!(SPSR & (1<<SPIF)));

  SPDR = b<<4 | r>>6;
  while(!(SPSR & (1<<SPIF)));

  SPDR = r << 2 | g>>8;
  while(!(SPSR & (1<<SPIF)));

  SPDR = g;
  while(!(SPSR & (1<<SPIF)));

}


void SB_WriteLEDData() {

  for (int f=0; f<totalLeds; f++) SB_SendPacket(B00, iCanales[totalLeds-f-1][0], iCanales[totalLeds-f-1][1], iCanales[totalLeds-f-1][2]);
  delayMicroseconds(15);
  digitalWrite(latchpin,HIGH);
  delayMicroseconds(15);
  digitalWrite(latchpin,LOW);

  for (int f=0; f< totalLeds; f++) SB_SendPacket(B01, 0, 0, 0);
  delayMicroseconds(15);
  digitalWrite(latchpin,HIGH);
  delayMicroseconds(15);
  digitalWrite(latchpin,LOW);

}


float fMap(float x, float in_min, float in_max, float out_min, float out_max){
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}



